<template>
  <div class="canvas-container">
    <canvas ref="canvasRef"></canvas>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref, watch } from 'vue';
import { useCanvasStore } from '../stores/canvas';
import { Application, Graphics, Container, Rectangle, Texture, Sprite, Text, TextStyle, TextMetrics } from 'pixi.js';
import { filters } from 'pixi.js';
import type { CanvasElement, TextElement, ImageElement, RectangleElement, CircleElement, TriangleElement } from '../types/canvas';

const { ColorMatrixFilter, BlurFilter } = filters;

const canvasRef = ref<HTMLCanvasElement>();
const canvasStore = useCanvasStore();

let app: Application;

/** 新增：worldLayer（会缩放的世界层）与 uiLayer（不缩放的 UI 层） */
let worldLayer: Container;
let uiLayer: Container;

let selectionGraphics: Graphics; 
let lastTextClickTime = 0;

const SCALE_HANDLE_SIZE = 8; 
const SCALE_HANDLE_FILL = 0x4a90e2; 
const SCALE_HANDLE_STROKE = 0xffffff; 

onMounted(() => {
  if (!canvasRef.value) return;

  app = new Application({
    view: canvasRef.value,
    width: canvasRef.value.clientWidth,
    height: canvasRef.value.clientHeight,
    backgroundColor: 0xffffff,
    resolution: window.devicePixelRatio || 1,
    autoDensity: true
  });

  // 初始化世界层与 UI 层
  worldLayer = new Container();
  uiLayer = new Container();
  // uiLayer 不随缩放变化
  uiLayer.scale.set(1);
  uiLayer.position.set(0, 0);

  // 把两个层加入 stage（worldLayer 在下面，uiLayer 在上层）
  app.stage.addChild(worldLayer);
  app.stage.addChild(uiLayer);

  // selectionGraphics 放到 uiLayer（不随缩放）
  selectionGraphics = new Graphics();
  uiLayer.addChild(selectionGraphics);
  
  window.addEventListener('resize', handleResize);
  handleResize();

  renderElements();
  setupCanvasInteractions();
});

const getScaleCursor = (handle: string): string => {
  switch (handle) {
    case 'nw': case 'se': return 'nwse-resize';
    case 'ne': case 'sw': return 'nesw-resize';
    case 'n': case 's': return 'ns-resize';
    case 'e': case 'w': return 'ew-resize';
    default: return 'default';
  }
};

const setupCanvasInteractions = () => {
  if (!app) return;

  app.stage.eventMode = 'static';
  app.stage.hitArea = app.screen;

  app.stage.on('wheel', (event) => {
    event.preventDefault();
    const wheelEvent = event.data.originalEvent as unknown as WheelEvent;
    canvasStore.zoom(wheelEvent.deltaY, wheelEvent.clientX, wheelEvent.clientY);
  });

  app.stage.on('pointerdown', (event) => {
    const mouseEvent = event.data.originalEvent as unknown as MouseEvent;
    // 中键或 Ctrl+左键平移
    if (mouseEvent.button === 1 || (mouseEvent.ctrlKey && mouseEvent.button === 0)) {
      event.stopPropagation();
      const pos = event.data.global;
      canvasStore.startPan(pos.x, pos.y);
      if (app.renderer.view.style) app.renderer.view.style.cursor = 'grabbing';
    } 
    // 左键点击空白处：框选
    else if (mouseEvent.button === 0 && event.target === app.stage) {
      const pos = event.data.global;
      if (!canvasStore.dragState.isDragging && !canvasStore.viewport.isPanning) {
        if (!mouseEvent.shiftKey) canvasStore.clearSelection();
        // 传递屏幕坐标给 Store，Store 会转为世界坐标
        canvasStore.startSelection(pos.x, pos.y);
        if (app.renderer.view.style) app.renderer.view.style.cursor = 'crosshair';
        renderSelectionBox();
      }
    }
  });

  app.stage.on('pointermove', (event) => {
    const pos = event.data.global;
    if (canvasStore.scaleState.isScaling) {
      canvasStore.updateScale(pos.x, pos.y);
      if (app.renderer.view.style) app.renderer.view.style.cursor = getScaleCursor(canvasStore.scaleState.scaleHandle);
    } else if (canvasStore.dragState.isDragging) {
      canvasStore.updateDrag(pos.x, pos.y);
      if (app.renderer.view.style) app.renderer.view.style.cursor = 'grabbing';
    } else if (canvasStore.viewport.isPanning) {
      canvasStore.updatePan(pos.x, pos.y);
      if (app.renderer.view.style) app.renderer.view.style.cursor = 'grabbing';
    } else if (canvasStore.selectionBox.isSelecting) {
      canvasStore.updateSelection(pos.x, pos.y);
      renderSelectionBox();
      if (app.renderer.view.style) app.renderer.view.style.cursor = 'crosshair';
    } else if (event.target !== app.stage) {
      if (app.renderer.view.style) app.renderer.view.style.cursor = 'grab';
    } else {
      if (app.renderer.view.style) app.renderer.view.style.cursor = 'default';
    }
  });

  const onPointerUp = (): void => {
    if (canvasStore.scaleState.isScaling) {
      canvasStore.endScale();
      if (app.renderer.view.style) app.renderer.view.style.cursor = 'default';
    }
    if (canvasStore.selectionBox.isSelecting) {
      canvasStore.endSelection();
      clearSelectionBox();
      if (app.renderer.view.style) app.renderer.view.style.cursor = 'default';
    }
    canvasStore.endDrag();
    canvasStore.endPan();
    if (app.renderer.view.style) app.renderer.view.style.cursor = 'default';
  };

  app.stage.on('pointerup', onPointerUp);
  app.stage.on('pointerupoutside', onPointerUp);
};

watch(() => [canvasStore.elements, canvasStore.viewport], () => renderElements(), { deep: true });

const handleResize = () => {
  if (!app || !canvasRef.value) return;
  const parent = canvasRef.value.parentElement;
  if (parent) app.renderer.resize(parent.clientWidth, parent.clientHeight);
};

// ✨✨ 优化：框选渲染 - 视觉线条粗细修正 ✨✨
const renderSelectionBox = () => {
  if (!selectionGraphics || !canvasStore.selectionBox.isSelecting) return;

  const { startX, startY, currentX, currentY } = canvasStore.selectionBox;

  // 关键修复：selectionBox存储的是世界坐标，但uiLayer不随缩放，需要转换为屏幕坐标
  const x1 = startX * canvasStore.viewport.scale + canvasStore.viewport.x;
  const y1 = startY * canvasStore.viewport.scale + canvasStore.viewport.y;
  const x2 = currentX * canvasStore.viewport.scale + canvasStore.viewport.x;
  const y2 = currentY * canvasStore.viewport.scale + canvasStore.viewport.y;

  const x = Math.min(x1, x2);
  const y = Math.min(y1, y2);
  const width = Math.abs(x2 - x1);
  const height = Math.abs(y2 - y1);

  selectionGraphics.clear();
  // 关键：线条粗细显示一致（UI 层已不缩放）
  const lineWidth = 2;
  selectionGraphics.lineStyle(lineWidth, 0x4a90e2, 0.8);
  selectionGraphics.beginFill(0x4a90e2, 0.1);
  selectionGraphics.drawRect(x, y, width, height);
  selectionGraphics.endFill();
};

const clearSelectionBox = () => selectionGraphics && selectionGraphics.clear();

const renderElements = () => {
  if (!app) return;

  // ✅ 不再清空整个 stage，改为只清空 worldLayer（所有会缩放的元素）
  worldLayer.removeChildren(); 

  worldLayer.x = canvasStore.viewport.x;
  worldLayer.y = canvasStore.viewport.y;
  worldLayer.scale.set(canvasStore.viewport.scale);

  const sortedElements = [...canvasStore.elements].sort((a, b) => (a.zIndex || 0) - (b.zIndex || 0));

  sortedElements.forEach(element => {
    let graphics;
    if ('type' in element) {
        const typedElement = element as { type: string };
        switch (typedElement.type) {
          case 'rectangle': graphics = createRectangle(element as RectangleElement); break;
          case 'circle': graphics = createCircle(element as CircleElement); break;
          case 'triangle': graphics = createTriangle(element as TriangleElement); break;
          case 'text': graphics = createText(element as TextElement); break;
          case 'image': graphics = createImage(element as ImageElement); break;
          default: console.warn('未知元素:', typedElement.type);
        }
      }
    if (graphics) worldLayer.addChild(graphics);
  });

  // selectionGraphics 位于 uiLayer（不随缩放），直接绘制或清空
  if (selectionGraphics) {
    if (canvasStore.selectionBox.isSelecting) renderSelectionBox();
    else selectionGraphics.clear();
  }
};

const hexToNumber = (hex: string) => {
    if (!hex || typeof hex !== 'string') return 0;
    return parseInt(hex.replace('#', ''), 16);
}

// --- 元素创建函数 ---

const createImage = (element: ImageElement): Container => {
  const container = new Container();
  const DEFAULT_SIZE = 200;
  const w = element.width ?? DEFAULT_SIZE;
  const h = element.height ?? DEFAULT_SIZE;

  const sprite = Sprite.from(element.src);
  sprite.width = w;
  sprite.height = h;
  sprite.alpha = element.opacity ?? 1;
  container.addChild(sprite as any);

  if (element.borderWidth > 0) {
    const border = new Graphics().lineStyle(element.borderWidth, hexToNumber(element.borderColor)).drawRect(0, 0, w, h);
    container.addChild(border as any);
  }

  applyFilter(sprite, element.filter || '无滤镜');

  if (element.selected) {
    const highlight = new Graphics().lineStyle(3 / canvasStore.viewport.scale, 0x4a90e2).drawRect(-2, -2, w + 4, h + 4);
    container.addChild(highlight as any);
    drawScaleHandles(container, 0, 0, w, h, element.id);
  }

  container.x = element.x;
  container.y = element.y;
  container.hitArea = new Rectangle(-5, -5, w + 10, h + 10);
  setupInteractive(container, element);
  return container;
};

const applyFilter = (sprite: Sprite, name: string): void => {
  sprite.filters = [];
  const m = new ColorMatrixFilter();
  switch (name) {
    case '灰度': m.grayscale(1, false); sprite.filters = [m]; break;
    case '复古': m.sepia(false); sprite.filters = [m]; break;
    case '反色': m.negative(false); sprite.filters = [m]; break;
    case '高饱和': m.saturate(2, false); sprite.filters = [m]; break;
    case '去饱和': m.saturate(0, false); sprite.filters = [m]; break;
    case '色相180°': m.hue(180, false); sprite.filters = [m]; break;
    case '提亮': m.brightness(1.3, false); sprite.filters = [m]; break;
    case '高对比': m.contrast(1.5, false); sprite.filters = [m]; break;
    case '模糊': sprite.filters = [new BlurFilter(8)]; break;
  }
};

const createRectangle = (element: CanvasElement): Container => {
  const container = new Container();
  const g = new Graphics();
  
  if ('background' in element) {
    g.beginFill(hexToNumber(element.background));
  }
  if ('borderWidth' in element && element.borderWidth > 0 && 'borderColor' in element) {
    g.lineStyle(element.borderWidth, hexToNumber(element.borderColor));
  }
  
  g.drawRect(0, 0, element.width, element.height);
  g.endFill();

  if (element.selected) {
    g.lineStyle(3 / canvasStore.viewport.scale, 0x4a90e2).drawRect(-2, -2, element.width + 4, element.height + 4);
    drawScaleHandles(container, 0, 0, element.width, element.height, element.id);
  }
  container.addChild(g as any);
  container.x = element.x;
  container.y = element.y;
  container.hitArea = new Rectangle(-5, -5, element.width + 10, element.height + 10);
  setupInteractive(container, element);
  return container;
};

const createCircle = (element: CanvasElement): Container => {
  const container = new Container();
  const g = new Graphics();
  const rx = element.width / 2, ry = element.height / 2;
  
  if ('background' in element) {
    g.beginFill(hexToNumber(element.background));
  }
  if ('borderWidth' in element && element.borderWidth > 0 && 'borderColor' in element) {
    g.lineStyle(element.borderWidth, hexToNumber(element.borderColor));
  }
  
  g.drawEllipse(rx, ry, rx, ry);
  g.endFill();

  if (element.selected) {
    g.lineStyle(3 / canvasStore.viewport.scale, 0x4a90e2).drawEllipse(rx, ry, rx + 2, ry + 2);
    drawScaleHandles(container, 0, 0, element.width, element.height, element.id);
  }
  container.addChild(g as any);
  container.x = element.x;
  container.y = element.y;
  container.hitArea = new Rectangle(-5, -5, element.width + 10, element.height + 10);
  setupInteractive(container, element);
  return container;
};

const createTriangle = (element: CanvasElement): Container => {
  const container = new Container();
  const g = new Graphics();
  const w = element.width, h = element.height;
  
  if ('background' in element) {
    g.beginFill(hexToNumber(element.background));
  }
  if ('borderWidth' in element && 'borderColor' in element) {
    g.lineStyle(element.borderWidth, hexToNumber(element.borderColor));
  }
  
  g.moveTo(w/2, 0).lineTo(0, h).lineTo(w, h).lineTo(w/2, 0);
  g.endFill();

  if (element.selected) {
    g.lineStyle(3 / canvasStore.viewport.scale, 0x4a90e2);
    g.moveTo(w/2, -3).lineTo(-3, h+3).lineTo(w+3, h+3).lineTo(w/2, -3);
    drawScaleHandles(container, 0, 0, w, h, element.id);
  }
  container.addChild(g as any);
  container.x = element.x;
  container.y = element.y;
  container.hitArea = new Rectangle(-5, -5, w + 10, h + 10);
  setupInteractive(container, element);
  return container;
};

const createText = (element: any) => {
  const container = new Container();
  const graphics = new Graphics(); 

  // 1. 初始化样式
  const style = new TextStyle({
    fontFamily: element.fontFamily || 'Arial, Helvetica, sans-serif',
    fontSize: Number(element.fontSize) || 16,
    fill: element.color || '#000000',
    fontWeight: element.bold ? 'bold' : 'normal',
    fontStyle: element.italic ? 'italic' : 'normal',
    align: element.textAlign || 'left', 
    wordWrap: true,
    wordWrapWidth: Number(element.width) || 200,
    breakWords: true,
    padding: 10,
    trim: true,
    textBaseline: 'middle'
  });

  // 2. 创建文本对象
  const textSprite = new Text(element.content, style);
  
  textSprite.style = style;
  textSprite.text = element.content;
  try {
    (textSprite as any).updateText && (textSprite as any).updateText();
  } catch (e) {
  }

  // 手动处理对齐
  if (element.textAlign === 'center') {
    textSprite.anchor.set(0.5, 0);
    textSprite.x = element.width / 2;
  } else if (element.textAlign === 'right') {
    textSprite.anchor.set(1, 0);
    textSprite.x = element.width;
  } else {
    textSprite.anchor.set(0, 0);
    textSprite.x = 0;
  }
  textSprite.y = 0;
  
  // 3. 绘制背景
  if (element.background && element.background !== 'transparent') {
    graphics.beginFill(hexToNumber(element.background));
  } else {
    graphics.beginFill(0x000000, 0); 
  }
  graphics.drawRect(0, 0, element.width, element.height);
  graphics.endFill();

  // 4. 选中状态高亮
  if (element.selected) {
    graphics.lineStyle(2 / canvasStore.viewport.scale, 0x4a90e2);
    graphics.drawRect(-2, -2, element.width + 4, element.height + 4);
    drawScaleHandles(container, 0, 0, element.width, element.height, element.id);
  }

  // 5. 组装
  container.addChild(graphics as any);
  container.addChild(textSprite as any);

  // ... (省略装饰线逻辑，保持不变，因为你之前的代码装饰线逻辑已经是好的) ...
  // ✨✨ 手动绘制线条 (修复多行渲染 & 消失Bug) ✨✨
  const drawStrikethrough = element.strikethrough;
  const drawUnderline = !drawStrikethrough && element.underline;

  if (drawStrikethrough || drawUnderline) {
    const lineGraphics = new Graphics();
    const lineColor = hexToNumber(element.color);
    lineGraphics.lineStyle(2, lineColor);

    const metrics = TextMetrics.measureText(element.content, style, element.wordWrap);
    const lineHeight = metrics.lineHeight;

    metrics.lines.forEach((lineText, i) => {
      const lineWidth = TextMetrics.measureText(lineText, style, element.wordWrap).width;
      let lineXOffset = 0;
      if (element.textAlign === 'center') {
        lineXOffset = (element.width - lineWidth) / 2;
      } else if (element.textAlign === 'right') {
        lineXOffset = element.width - lineWidth;
      }
      const finalStartX = lineXOffset; 
      const finalEndX = finalStartX + lineWidth;
      const lineTopY = textSprite.y + i * lineHeight;

      if (drawStrikethrough) {
        const strikeY = lineTopY + lineHeight * 0.55;
        lineGraphics.moveTo(finalStartX, strikeY);
        lineGraphics.lineTo(finalEndX, strikeY);
      } else if (drawUnderline) {
        const underlineY = lineTopY + lineHeight * 0.92;
        lineGraphics.moveTo(finalStartX, underlineY);
        lineGraphics.lineTo(finalEndX, underlineY);
      }
    });

    container.addChild(lineGraphics);
  }

  // 位置与交互
  container.x = element.x;
  container.y = element.y;
  container.eventMode = 'static';
  container.cursor = 'text';
  container.hitArea = new Rectangle(0, 0, element.width, element.height);

  container.on('pointerdown', (event) => {
    event.stopPropagation();
    const currentTime = Date.now();
    if (currentTime - lastTextClickTime < 300) {
      startTextEdit(element); // 双击编辑
      lastTextClickTime = 0;
      return;
    }
    lastTextClickTime = currentTime;
    
    const pos = event.data.global;
    if ((event.data.originalEvent as unknown as KeyboardEvent).shiftKey) {
      canvasStore.toggleElementSelection(element.id);
    } else {
      if (!element.selected) canvasStore.selectElement(element.id);
    }
    canvasStore.bringToFront();
    container.scale.set(1.05);
    setTimeout(() => container.scale.set(1.0), 150);

    // ✅ 关键：把屏幕坐标转换为世界坐标后再 startDrag（统一世界坐标）
    const world = canvasStore.screenToWorld(pos.x, pos.y);
    canvasStore.startDrag(element.id, world.x, world.y);
  });

  return container;
};

const setupInteractive = (container: Container, element: any) => {
  container.eventMode = 'static';
  container.cursor = 'pointer';
  container.on('pointerover', () => container.cursor = 'grab');
  container.on('pointerout', () => container.cursor = 'pointer');
  container.on('pointerdown', (e) => {
    e.stopPropagation();
    container.cursor = 'grabbing';
    const global = e.data.global;

    if ((e.data.originalEvent as unknown as KeyboardEvent).shiftKey) canvasStore.toggleElementSelection(element.id);
    else if (!element.selected) canvasStore.selectElement(element.id);
    
    canvasStore.bringToFront();
    container.scale.set(1.05);
    setTimeout(() => container.scale.set(1.0), 150);

    // ✅ 关键：统一传入世界坐标（screen -> world）
    const world = canvasStore.screenToWorld(global.x, global.y);
    canvasStore.startDrag(element.id, world.x, world.y);
  });
  container.on('pointerup', () => container.cursor = 'grab');
};

// ✨✨ 优化：缩放手柄 - 视觉大小修正 ✨✨
const drawScaleHandles = (container: Container, x: number, y: number, w: number, h: number, id: string) => {
  const handles = [
    { id: 'nw', x: x, y: y, c: 'nwse-resize' },
    { id: 'n', x: x + w/2, y: y, c: 'ns-resize' },
    { id: 'ne', x: x + w, y: y, c: 'nesw-resize' },
    { id: 'e', x: x + w, y: y + h/2, c: 'ew-resize' },
    { id: 'se', x: x + w, y: y + h, c: 'nwse-resize' },
    { id: 's', x: x + w/2, y: y + h, c: 'ns-resize' },
    { id: 'sw', x: x, y: y + h, c: 'nesw-resize' },
    { id: 'w', x: x, y: y + h/2, c: 'ew-resize' }
  ];

  handles.forEach(hdl => {
    const g = new Graphics();
    // 关键：除以 scale，确保手柄视觉大小不变
    const size = SCALE_HANDLE_SIZE / canvasStore.viewport.scale; 
    g.beginFill(SCALE_HANDLE_FILL).lineStyle(1 / canvasStore.viewport.scale, SCALE_HANDLE_STROKE);
    g.drawRect(hdl.x - size/2, hdl.y - size/2, size, size);
    g.endFill();
    g.eventMode = 'static';
    g.cursor = hdl.c;
    g.on('pointerdown', (e) => {
      e.stopPropagation();
      e.data.originalEvent.preventDefault();
      // startScale 在 store 端期望屏幕坐标（startX,startY），因此我们传入屏幕坐标
      canvasStore.startScale(id, hdl.id, e.data.global.x, e.data.global.y);
    });
    container.addChild(g as any);
  });
};

const startTextEdit = (element: any) => {
  const parent = app.view.parentElement;
  if (!parent) return;

  const textarea = document.createElement('textarea');
  const scale = canvasStore.viewport.scale;
  const x = element.x * scale + canvasStore.viewport.x;
  const y = element.y * scale + canvasStore.viewport.y;

  textarea.value = element.content;
  textarea.style.position = 'absolute';
  textarea.style.left = `${x}px`;
  textarea.style.top = `${y}px`;
  textarea.style.width = `${element.width * scale}px`;
  textarea.style.height = `${element.height * scale}px`;
  textarea.style.fontSize = `${element.fontSize * scale}px`;
  textarea.style.fontFamily = element.fontFamily;
  textarea.style.color = element.color;
  textarea.style.textAlign = element.textAlign;
  textarea.style.fontWeight = element.bold ? 'bold' : 'normal';
  textarea.style.fontStyle = element.italic ? 'italic' : 'normal';
  textarea.style.textDecoration = element.strikethrough ? 'line-through' : (element.underline ? 'underline' : 'none');
  textarea.style.background = element.background === 'transparent' ? 'rgba(255,255,255,0.8)' : element.background;
  
  textarea.style.border = '1px dashed #4a90e2';
  textarea.style.outline = 'none';
  textarea.style.padding = '0';
  textarea.style.margin = '0';
  textarea.style.resize = 'none';
  textarea.style.zIndex = '1000';

  const finish = (): void => {
    if (textarea.value !== element.content) {
      canvasStore.updateElement(element.id, { content: textarea.value });
    }
    if (textarea.parentNode) textarea.parentNode.removeChild(textarea);
  };

  textarea.onblur = finish;
  textarea.onkeydown = (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      finish();
    }
    if (e.key === 'Escape') textarea.remove();
    e.stopPropagation();
  };

  parent.appendChild(textarea);
  setTimeout(() => { textarea.focus(); textarea.select(); }, 10);
};

onUnmounted(() => {
  if (app) app.destroy(true, { children: true, texture: true, baseTexture: true });
  window.removeEventListener('resize', handleResize);
});
</script>

<style scoped>
.canvas-container {
  width: 100%;
  height: 100%;
  background: #f5f5f5;
  position: relative;
  overflow: hidden;
}

canvas {
  display: block;
  width: 100%;
  height: 100%;
}
</style>
